package myomi.ant.taskdefs;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;

import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.taskdefs.MatchingTask;
import org.apache.tools.ant.types.Path;

import sun.misc.CharacterEncoder;
import sun.misc.HexDumpEncoder;

public class Dump extends MatchingTask {
	
	private Path classDirs;
	private File destDir;

	public Dump() throws ClassNotFoundException, SecurityException, NoSuchMethodException {
		super();
	}

	public void setClassDir(Path classDir) {
		if (classDirs == null) {
			classDirs = classDir;
		} else {
			classDirs.append(classDir);
		}
	}
	
	public void setDestDir(File destDir) {
		this.destDir = destDir;
	}
	
	public void execute() {
		log("start dump task");
		try {
			for (String dir: classDirs.list()) {
				File f = getProject().resolveFile(dir);
				DirectoryScanner scanner = getDirectoryScanner(f);
				String[] classes = scanner.getIncludedFiles();
				for (String classPath: classes) {
					javap(dir, classPath);					
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		log("end dump task");
	}
	
	private void javap(String classDir, String classPath) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, SecurityException, NoSuchMethodException, ClassNotFoundException, IOException {
		FileInputStream in = null;
		FileOutputStream out = null;
		try {
			// mkdir
			File tmp = new File(destDir.getAbsolutePath() + File.separator + classPath);
			File dir = tmp.getParentFile();
			if (!dir.exists()) dir.mkdirs();
			// dump
			in = new FileInputStream(classDir + File.separator + classPath);
			File file = new File(dir, tmp.getName().replaceAll(".class", ".dump"));
			out = new FileOutputStream(file);
			CharacterEncoder encoder = new HexDumpEncoder();
			encoder.encodeBuffer(in, out);
			log("execute dump: " + file.getAbsolutePath());
		} finally {
			try {
				if (in != null) in.close();
			} finally {
				if (out != null) out.close();
			}
		}
	}
}
